package server

import (
	"notabug.org/apiote/next-eeze/fs"
	"notabug.org/apiote/next-eeze/password"

	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

type SessionResult struct {
	Success bool
	Keys    interface{}
}

// todo memguard credentials
func open(credentials fs.Credentials) (string, error) {
	// todo memguard
	req, err := http.NewRequest("POST",
		credentials.Server+"/index.php/apps/passwords/api/1.0/session/open",
		bytes.NewBuffer([]byte("{}")))

	if err != nil {
		log.Fatal("Error reading request. ", err)
		return "", err
	}

	req.Header.Set("Accept", "application/json")
	req.SetBasicAuth(credentials.Username, credentials.Password)
	
	client := &http.Client{Timeout: time.Second * 30}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal("Error reading response. ", err)
		return "", err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Error reading body. ", err)
		return "", err
	}

	sessionResult := SessionResult{}
	err = json.Unmarshal(body, &sessionResult)
	if err != nil {
		log.Fatal("Error unmarshalling body. ", err)
		return "", err
	}
	if !sessionResult.Success {
		log.Fatal("Error authenticating.")
		return "", errors.New("No success")
	}

	// todo memguard
	session := resp.Header.Get("x-api-session")
	return session, nil
}

// todo memguard credentials, session
func list(credentials fs.Credentials, session string) ([]password.NextPassword, error) {
	// todo memguard
	authorization := base64.StdEncoding.EncodeToString([]byte(credentials.Username + ":" + credentials.Password))

	// todo memguard
	passwords := []password.NextPassword{}
	req, err := http.NewRequest("POST",
		credentials.Server+"/index.php/apps/passwords/api/1.0/password/list",
		bytes.NewBuffer([]byte("{}")))

	if err != nil {
		log.Fatal("Error reading request. ", err)
		return passwords, err
	}

	req.Header.Set("Accept", "application/json")
	req.Header.Set("x-api-session", session)
	req.Header.Set("Authorization", "Basic "+authorization)

	client := &http.Client{Timeout: time.Second * 10}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal("Error reading response. ", err)
		return passwords, err
	}
	defer resp.Body.Close()

	// todo memguard
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal("Error reading body. ", err)
		return passwords, err
	}

	err = json.Unmarshal(body, &passwords)
	if err != nil {
		log.Fatal("Error unmarshalling body. ", err)
		return nil, err
	}

	return passwords, nil
}

// todo memguard masterPassword
func Sync(masterPassword string) error {
	// todo memguard
	credentials, err := fs.ReadCredentials(masterPassword)
	if err != nil {
		return err
	}

	// todo memguard
	session, err := open(credentials)
	if err != nil {
		return err
	}
	// todo memguard
	passwords, err := list(credentials, session)
	if err != nil {
		return err
	}
	err = fs.Save(passwords, masterPassword)
	if err != nil {
		return err
	}
	return nil
}
